/* -----------------------------------------------------
 iCompose
 MainView.m
 
 Created by Team: THE BEARD on 18/10/09
 Members who contributed to this file:
 1. Ethan Holmes
 
 List of Bugs:
 1. Does not load up notes on screen after save and application exit.
 
 Simon Fraser University, 2009.
 ----------------------------------------------------- */

#import "MainView.h"

@implementation MainView

@synthesize staff;
@synthesize gestureStartPoint;
@synthesize lastPosition;
@synthesize currentBarView;
@synthesize lastPitchView;
@synthesize lastPositionView;
@synthesize noteImage;
//@synthesize barViews;
@synthesize samplePlayer;
@synthesize isPlayingSample;

@synthesize C1;
@synthesize D1;
@synthesize E1;
@synthesize F1;
@synthesize G1;
@synthesize A1;
@synthesize B1;
@synthesize C2;
@synthesize D2;
@synthesize E2;
@synthesize F2;
@synthesize G2;
@synthesize A2;

@synthesize eighth1View;
@synthesize eighth2View;
@synthesize eighth3View;
@synthesize eighth4View;
@synthesize eighth5View;
@synthesize eighth6View;
@synthesize eighth7View;
@synthesize eighth8View;

@synthesize quarter1View;
@synthesize quarter2View;
@synthesize quarter3View;
@synthesize quarter4View;

@synthesize half1View;
@synthesize half2View;

@synthesize wholeView;

@synthesize staffList;
@synthesize pitchList;

@synthesize eighthList;
@synthesize quarterList;
@synthesize halfList;

@synthesize staffBox;
@synthesize eighthButton;
@synthesize wholeButton;
@synthesize halfButton;
@synthesize quarterButton;
@synthesize infoButton;
@synthesize barLabel;
@synthesize noteBox;

-(void)initStaffState:(TimeSignature*)time andTempo:(Tempo*)speed andInstrument:(InstrumentPlayer*) player andName:(NSString*)name{
	staff = [Staff alloc];
	[staff initStaff: time andTempo: speed andInstrument: player andName:name];
}

/*
 An actionsheet is issued to give the player multiple options:
 1. Save
 2. Quit without saving
 3. Cancel
*/
-(IBAction)saveStaff {
	UIActionSheet *menu = [[UIActionSheet alloc] initWithTitle:@"Choose an option" delegate: self cancelButtonTitle:@"Cancel" destructiveButtonTitle: nil otherButtonTitles: @"Save", @"Quit without saving", nil];
	[menu showInView: self.view];
	[menu release];
}

-(void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
	if(buttonIndex == 0) {
		iComposeAppDelegate *mainDelegate = (iComposeAppDelegate*)[[UIApplication sharedApplication] delegate];
		bool new = true;
		Staff *tempStaff;
		for(int i = 0; i < [mainDelegate.staffArray count]; i++) {
			tempStaff = [[mainDelegate.staffArray objectAtIndex: i] staff];
			if([tempStaff.nameOfComposition isEqual: staff.nameOfComposition]) {
				[mainDelegate.staffArray insertObject: self atIndex: i];
				[mainDelegate.staffArray removeObjectAtIndex: (i + 1)];
				new = false;
			}
			NSLog(@"%i", [mainDelegate.staffArray count]);
		}
		if(new == true) {
			[mainDelegate.staffArray insertObject: self atIndex: [mainDelegate.staffArray count]];
			NSLog(@"%i", [mainDelegate.staffArray count]);
		}
		[self.parentViewController back];
	}
	else if(buttonIndex == 1) {
		//[staff release];
		[self.parentViewController back];
	}
}

/*
 Plays all the notes in the application.
*/ 
-(IBAction)play {
	[staff play];
}

/*
 Stops the audio player.
*/
-(IBAction)stop {
	[staff stop];
}

/*
 When the user presses any note button in the NoteBox an image of the correct note will be displayed on the button.
 The image will follow the user's finger until lift their finger off of the iPhone / iPod Touch screen.
*/
-(void)noteButtonCreated:(UIControl*)noteButton withEvent:(UIEvent *)event {
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];
	
	// Selects the correct note head image to display.
	int position = noteButton.tag % 1000;
	UIImage *image = [self getImage: position];
	
	// Initializes a temporary image view the user will drag with their finger.
	noteImage = [[UIImageView alloc] initWithImage: image];
	int height = 30;
	if(position == 0) {
		height = 26;
	}
	noteImage.frame = CGRectMake(location.x - 20, location.y - 15, 40, height);
	[self.view addSubview: noteImage];
}

/*
 Returns a UIImage according to a position. 
*/
-(UIImage*)getImage:(int)position {
	switch (position) {
		case 0:
			return [UIImage imageNamed:@"whole.png"];
		case 1:
			return  [UIImage imageNamed:@"halfHead.png"];
		case 2:
			return  [UIImage imageNamed:@"quarterHead.png"];
		case 3:
			return  [UIImage imageNamed:@"quarterHead.png"];
	}
	return nil;
}

/*
 Returns a UIImage according to a position. 
 */
-(UIImage*)getTailImage:(int)position andTail:(BOOL)noteTail {
	switch (position) {
		case 0:
			return [UIImage imageNamed:@"whole.png"];
		case 1:
			if(noteTail) {
				return [UIImage imageNamed:@"halfUp.png"];
			}
			return [UIImage imageNamed:@"halfDown.png"];
		case 2:
			if(noteTail) {
				return [UIImage imageNamed:@"quarterUp.png"];
			}
			return [UIImage imageNamed:@"quarterDown.png"];
		case 3:
			if(noteTail) {
				return [UIImage imageNamed:@"eighthUp.png"];
			}
			return [UIImage imageNamed:@"eighthDown.png"];
	}
	return nil;
}

// Touch event associated to note buttons
-(void)noteButtonDraggedOut:(UIControl*)noteButton withEvent:(UIEvent *)event {
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];
		
	[self clearViews];
	
	if (noteImage != nil) {
		noteImage.center = location;
	}
	
	int position = noteButton.tag % 1000;
	[self highlightSelected: position withPoint: location];
}

// Touch event associated to note buttons
-(void)noteButtonDropped:(UIControl*)noteButton withEvent:(UIEvent *)event {
	NodeButton *button = [[NodeButton buttonWithType:UIButtonTypeCustom] retain];
	NoteNode *dropNode;
	
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];
	
	if ((CGRectContainsPoint(noteBox.frame, location)) == 1) {
		[button release];
		return;
	}
	
	int shift = -39;
	BOOL noteTail; // TRUE = UP, FALSE = DOWN.
	if (noteImage.center.y >= 158.5) {
		noteTail = TRUE;
	}
	else {
		noteTail = FALSE;
		shift = 39;
	}
	
	int pitch = [self getPitch: location];
	int position = noteButton.tag % 1000;
	NodeView *tempView;

	switch (position) {
		case 0:
			tempView = wholeView;
			break;
		case 1:
			tempView = [self getView: halfList withPoint: location];
			break;
		case 2:
			tempView = [self getView: quarterList withPoint: location];
			break;
		case 3:
			tempView = [self getView: eighthList withPoint: location];
			break;
	}
	
	dropNode = tempView.owner;
	if (dropNode.isNote) {
		[self clearViews];
		[self removeImageView];
		[button release];
		return;
	}

	UIImage *image = [self getTailImage: position andTail: noteTail];
	int width = 29;
	int height = 102;

	if(position == 0) {
		width = CGRectGetWidth(noteImage.frame);
		height = CGRectGetHeight(noteImage.frame);
		shift = 0;
	}
	else if(position == 3 && noteTail) {
		width = 54;
	}
	button.frame = CGRectMake(0, 0, width, height);
	[button setBackgroundImage: image forState:UIControlStateNormal];
	button.tag = noteButton.tag;
	
	UIView *pitchView = [self getView: staffList withPoint: location];
	location.y = pitchView.center.y + shift;
	location.x = tempView.center.x;
	CGPoint point = [currentBarView convertPoint: location fromView: self.view];
	button.center = point;
	
	[button addTarget:self action:@selector(noteDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
	[button addTarget:self action:@selector(notePickedUp:withEvent:) forControlEvents: UIControlEventTouchDown];
	[button addTarget:self action:@selector(noteDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside |  UIControlEventTouchUpInside];
	
	[[staff.barList objectAtIndex:staff.currentBar] insertNoteAt:tempView.owner withPitch:pitch andButton:button];
	[currentBarView addSubview:button];
	
	button.owner = tempView.owner;
	
	[self clearViews];
	[self removeImageView];
	[[staff.barList objectAtIndex:staff.currentBar] drawBar];
}

/*
 Returns a pitch associated with a CGPoint.
*/
-(int)getPitch:(CGPoint)location {
	UIView *pitchView = [self getView: staffList withPoint: location];
	if (pitchView == nil) return -1;
	int pitchPositon = [staffList indexOfObject: pitchView];
	NSNumber *pitch = [pitchList objectAtIndex: pitchPositon];
	return [pitch intValue];
}

/*
 Checks all views in list for the CGPoint and returns the assoicated UIView.
*/
-(NodeView*)getView:(NSMutableArray*)list withPoint:(CGPoint)location {
	for(NodeView *tempView in list) {
		if ([tempView pointInside:[tempView convertPoint:location fromView:self.view] withEvent:nil]) {
			return tempView;
		}
	}
	return nil;
}

// Touch event associated to node buttons
-(void)notePickedUp:(NodeButton*)noteButton withEvent:(UIEvent *)event {
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];
	int position = noteButton.tag % 1000;
	UIImage *image = [self getImage: position];
	
	// Initializes a temporary image view the user will drag with their finger.
	noteImage = [[UIImageView alloc] initWithImage: image];
	int height = 30;
	if(position == 0) {
		height = 26;
	}
	[noteButton setBackgroundImage: image forState:UIControlStateNormal];
	noteButton.frame = CGRectMake(location.x - 20, location.y - 15, 40, height);
}

// Touch event associated to node buttons
-(void)noteDraggedOut:(NodeButton*)noteButton withEvent:(UIEvent *)event {
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];
	[self clearViews];
	CGPoint point = [currentBarView convertPoint: location fromView: self.view];
	noteButton.center = point;
	int position = noteButton.tag % 1000;
	[self highlightSelected: position withPoint: location];
}

/*
 Touch event associated to node buttons
 */
-(void)noteDropped:(NodeButton*)noteButton withEvent:(UIEvent *)event {
	UITouch *touch = [[event allTouches] anyObject];
	CGPoint location = [touch locationInView: self.view];

	if ((CGRectContainsPoint(noteBox.frame, location)) == 1) {
		[[staff.barList objectAtIndex:staff.currentBar] removeNoteAt:noteButton.owner];
		[self clearViews];
		[[staff.barList objectAtIndex:staff.currentBar] drawBar];
		return;
	}

	int pitch = [self getPitch: location];
	if(pitch == -1) {
		noteButton.center = [currentBarView convertPoint: lastPosition fromView: self.view];
		[self clearViews];
		[[staff.barList objectAtIndex:staff.currentBar] drawBar];
		return;
	}
	
	int shift = -39;
	BOOL noteTail; // TRUE = UP, FALSE = DOWN.
	if (noteButton.center.y >= 118.5) {
		noteTail = TRUE;
	}
	else {
		noteTail = FALSE;
		shift = 39;
	}
	
	int position = noteButton.tag % 1000;
	NodeView *tempView;
	switch (position) {
		case 0:
			tempView = wholeView;
			break;
		case 1:
			tempView = [self getView: halfList withPoint: location];
			break;
		case 2:
			tempView = [self getView: quarterList withPoint: location];
			break;
		case 3:
			tempView = [self getView: eighthList withPoint: location];
			break;
	}
	
	if (tempView.owner != noteButton.owner) {
		[[staff.barList objectAtIndex:staff.currentBar] removeNoteAt:noteButton.owner];
	}
	
	UIImage *image = [self getTailImage: position andTail: noteTail];
	int width = 29;
	int height = 102;
	
	if(position == 0) {
		width = 40;
		height = 26;
		shift = 0;
	}
	else if(position == 3 && noteTail) {
		width = 54;
	}
	noteButton.frame = CGRectMake(0, 0, width, height);
	[noteButton setBackgroundImage: image forState:UIControlStateNormal];
	
	UIView *pitchView = [self getView: staffList withPoint: location];
	location.y = pitchView.center.y + shift;
	location.x = tempView.center.x;
	
	CGPoint point = [currentBarView convertPoint: location fromView: self.view];
	noteButton.center = point;
	
	[[staff.barList objectAtIndex:staff.currentBar] insertNoteAt:tempView.owner withPitch:pitch andButton:noteButton];
	
	noteButton.owner = tempView.owner;
	
	[self clearViews];
	[[staff.barList objectAtIndex:staff.currentBar] drawBar];
	
}

// After noteButton is done the imageView is removed from the mainView.
-(void)removeImageView {
	[noteImage removeFromSuperview];
	[noteImage release];
	noteImage = nil;
}

/*
 Highlights spaced on the staff which the user traverses with their finger.
 */
-(void)highlightSelected:(int)position withPoint:(CGPoint)location {
	
	NSMutableArray *tempList;
	switch (position) {
		case 0:
			tempList = [[NSMutableArray alloc] initWithCapacity: 0];
			[tempList addObject: wholeView];
			[self highlightStaff: location withList: tempList andType: 1];
			[tempList release];
			break;
		case 1:
			[self highlightStaff: location withList: halfList andType: 1];
			break;
		case 2:
			[self highlightStaff: location withList: quarterList andType: 1];
			break;
		case 3:
			[self highlightStaff: location withList: eighthList andType: 1];
			break;
	}
	[self highlightStaff: location withList: staffList andType: 0];
}

/*
 When the button is hovering over a view on the staff the alpha of the view is set to 0.3.
 Once the button has hovered off of the view then its alpha is set back to 0.
 */
-(void)highlightStaff:(CGPoint)location withList:(NSMutableArray*)list andType:(int)type {
	NodeView *tempView;
	
	for(int i = 0; i < [list count]; i++) {
		tempView = [list objectAtIndex: i];
		if ([tempView pointInside:[tempView convertPoint:location fromView:self.view] withEvent:nil]) {
			switch(type) {
				case 0:
					[tempView setAlpha:0.4];
					if (tempView != isPlayingSample) {
						[self playSample:tempView];
					}
					break;
				case 1:
					[self setAlphas:tempView.owner];
					break;
			}
		}
	}
}

/*
 Sets alphas of all 'parent' view to aid in note placement
 */
-(void)setAlphas:(NoteNode*)currView {
	while (currView.parent != nil){
		[currView.noteView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.2]];
		currView = currView.parent;
	}
	[currView.noteView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.1]];
}

/*
 Clear all views in MainView.
*/
-(void)clearViews {
	for(UIView *view in staffList) {
		[view setAlpha: 0.0];
	}
	for(UIView *view in halfList) {
		[view setBackgroundColor:[UIColor clearColor]];
	}
	for(UIView *view in quarterList) {
		[view setBackgroundColor:[UIColor clearColor]];
	}
	for(UIView *view in eighthList) {
		[view setBackgroundColor:[UIColor clearColor]];
	}
	[wholeView setBackgroundColor:[UIColor clearColor]];
}

/*
 When the i button is pressed the screen is flipped. Here the user can change Tempo without making a new file.
*/
-(IBAction)infoButtonPressed:(id)sender {
	MainOptionsView *mainOptionsView = [[MainOptionsView alloc] initWithNibName: @"MainOptionsView" bundle: nil];
	mainOptionsView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
	[mainOptionsView setSpeed: [[staff tempo] speed]];
	NSLog(@"tempo: %i", [[staff tempo] speed]);
	[self presentModalViewController: mainOptionsView animated: YES];
	[mainOptionsView release];
}

/*
 // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
 // Custom initialization
 }
 return self;
 }
 */

-(UIView*)getCurrentBarView {
	return [[staff.barList objectAtIndex: staff.currentBar] barView];
}

-(void)connectNodeViews {
	NSLog(@"connecting nodes with views");
	Bar *tempBar = [staff.barList objectAtIndex:staff.currentBar];
	tempBar.noteTree.wholeNode.noteView = wholeView;
	
	tempBar.noteTree.half1Node.noteView = half1View;
	tempBar.noteTree.half2Node.noteView = half2View;
	
	tempBar.noteTree.quarter1Node.noteView = quarter1View;
	tempBar.noteTree.quarter2Node.noteView = quarter2View;
	tempBar.noteTree.quarter3Node.noteView = quarter3View;
	tempBar.noteTree.quarter4Node.noteView = quarter4View;
	
	tempBar.noteTree.eighth1Node.noteView = eighth1View;
	tempBar.noteTree.eighth2Node.noteView = eighth2View;
	tempBar.noteTree.eighth3Node.noteView = eighth3View;
	tempBar.noteTree.eighth4Node.noteView = eighth4View;
	tempBar.noteTree.eighth5Node.noteView = eighth5View;
	tempBar.noteTree.eighth6Node.noteView = eighth6View;
	tempBar.noteTree.eighth7Node.noteView = eighth7View;
	tempBar.noteTree.eighth8Node.noteView = eighth8View;
	
	wholeView.owner = tempBar.noteTree.wholeNode;
	
	half1View.owner = tempBar.noteTree.half1Node;
	half2View.owner = tempBar.noteTree.half2Node;
	
	quarter1View.owner = tempBar.noteTree.quarter1Node;
	quarter2View.owner = tempBar.noteTree.quarter2Node;
	quarter3View.owner = tempBar.noteTree.quarter3Node;
	quarter4View.owner = tempBar.noteTree.quarter4Node;
	
	eighth1View.owner = tempBar.noteTree.eighth1Node;
	eighth2View.owner = tempBar.noteTree.eighth2Node;
	eighth3View.owner = tempBar.noteTree.eighth3Node;
	eighth4View.owner = tempBar.noteTree.eighth4Node;
	eighth5View.owner = tempBar.noteTree.eighth5Node;
	eighth6View.owner = tempBar.noteTree.eighth6Node;
	eighth7View.owner = tempBar.noteTree.eighth7Node;
	eighth8View.owner = tempBar.noteTree.eighth8Node;
	
	[staff.barList replaceObjectAtIndex:staff.currentBar withObject:tempBar];
}

-(void)makeLists{
	// set list of pitches & staff list containing the UIViews laying overtop of each line and space.
	NSNumber *pNum;
	staffList = [[NSMutableArray alloc] initWithCapacity:0];
	pitchList = [[NSMutableArray alloc] initWithCapacity:0];
	
	[staffList addObject: C1];
	pNum = [[NSNumber alloc] initWithInt: 100];
	[pitchList addObject: pNum];
	[staffList addObject: D1];
	pNum = [[NSNumber alloc] initWithInt: 102];
	[pitchList addObject: pNum];
	[staffList addObject: E1];
	pNum = [[NSNumber alloc] initWithInt: 104];
	[pitchList addObject: pNum];
	[staffList addObject: F1];
	pNum = [[NSNumber alloc] initWithInt: 105];
	[pitchList addObject: pNum];
	[staffList addObject: G1];
	pNum = [[NSNumber alloc] initWithInt: 107];
	[pitchList addObject: pNum];
	[staffList addObject: A1];
	pNum = [[NSNumber alloc] initWithInt: 109];
	[pitchList addObject: pNum];
	[staffList addObject: B1];
	pNum = [[NSNumber alloc] initWithInt: 111];
	[pitchList addObject: pNum];
	[staffList addObject: C2];
	pNum = [[NSNumber alloc] initWithInt: 112];
	[pitchList addObject: pNum];
	[staffList addObject: D2];
	pNum = [[NSNumber alloc] initWithInt: 114];
	[pitchList addObject: pNum];
	[staffList addObject: E2];
	pNum = [[NSNumber alloc] initWithInt: 116];
	[pitchList addObject: pNum];
	[staffList addObject: F2];
	pNum = [[NSNumber alloc] initWithInt: 117];
	[pitchList addObject: pNum];
	[staffList addObject: G2];
	pNum = [[NSNumber alloc] initWithInt: 119];
	[pitchList addObject: pNum];
	[staffList addObject: A2];
	pNum = [[NSNumber alloc] initWithInt: 121];
	[pitchList addObject: pNum];
	
	eighthList = [[NSMutableArray alloc] initWithCapacity: 0];
	[eighthList addObject: eighth1View];
	[eighthList addObject: eighth2View];
	[eighthList addObject: eighth3View];
	[eighthList addObject: eighth4View];
	[eighthList addObject: eighth5View];
	[eighthList addObject: eighth6View];
	[eighthList addObject: eighth7View];
	[eighthList addObject: eighth8View];
	
	quarterList = [[NSMutableArray alloc] initWithCapacity: 0];
	[quarterList addObject: quarter1View];
	[quarterList addObject: quarter2View];
	[quarterList addObject: quarter3View];
	[quarterList addObject: quarter4View];
	
	halfList = [[NSMutableArray alloc] initWithCapacity: 0];
	[halfList addObject: half1View];
	[halfList addObject: half2View];	
}

-(void)setViews {
	// set up reactive NodeViews
	wholeView = [[NodeView alloc] initWithFrame:CGRectMake(80, 61, 400, 195)];
	
	half1View = [[NodeView alloc] initWithFrame:CGRectMake(80, 61, 200, 195)];
	half2View = [[NodeView alloc] initWithFrame:CGRectMake(280, 61, 200, 195)];
	
	quarter1View = [[NodeView alloc] initWithFrame:CGRectMake(80, 61, 100, 195)];
	quarter2View = [[NodeView alloc] initWithFrame:CGRectMake(180, 61, 100, 195)];
	quarter3View = [[NodeView alloc] initWithFrame:CGRectMake(280, 61, 100, 195)];
	quarter4View = [[NodeView alloc] initWithFrame:CGRectMake(380, 61, 100, 195)];
	
	eighth1View = [[NodeView alloc] initWithFrame:CGRectMake(80, 61, 50, 195)];
	eighth2View = [[NodeView alloc] initWithFrame:CGRectMake(130, 61, 50, 195)];
	eighth3View = [[NodeView alloc] initWithFrame:CGRectMake(180, 61, 50, 195)];
	eighth4View = [[NodeView alloc] initWithFrame:CGRectMake(230, 61, 50, 195)];
	eighth5View = [[NodeView alloc] initWithFrame:CGRectMake(280, 61, 50, 195)];
	eighth6View = [[NodeView alloc] initWithFrame:CGRectMake(330, 61, 50, 195)];
	eighth7View = [[NodeView alloc] initWithFrame:CGRectMake(380, 61, 50, 195)];
	eighth8View = [[NodeView alloc] initWithFrame:CGRectMake(430, 61, 50, 195)];
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
	lastPitchView = nil;
	
	// set whole note button methods.
	[wholeButton addTarget:self action:@selector(noteButtonCreated:withEvent:) forControlEvents: UIControlEventTouchDown];
	[wholeButton addTarget:self action:@selector(noteButtonDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
	[wholeButton addTarget:self action:@selector(noteButtonDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside | UIControlEventTouchUpInside];
	wholeButton.tag = 1000;
	
	// set half note button methods.
	[halfButton addTarget:self action:@selector(noteButtonCreated:withEvent:) forControlEvents: UIControlEventTouchDown];
	[halfButton addTarget:self action:@selector(noteButtonDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
	[halfButton addTarget:self action:@selector(noteButtonDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside | UIControlEventTouchUpInside];
	halfButton.tag = 1001;
	
	// set quarter note button methods.
	[quarterButton addTarget:self action:@selector(noteButtonCreated:withEvent:) forControlEvents: UIControlEventTouchDown];
	[quarterButton addTarget:self action:@selector(noteButtonDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
	[quarterButton addTarget:self action:@selector(noteButtonDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside | UIControlEventTouchUpInside];
	quarterButton.tag = 1002;
	
	// set eighth note button methods.
	[eighthButton addTarget:self action:@selector(noteButtonCreated:withEvent:) forControlEvents: UIControlEventTouchDown];
	[eighthButton addTarget:self action:@selector(noteButtonDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
	[eighthButton addTarget:self action:@selector(noteButtonDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside | UIControlEventTouchUpInside];
	eighthButton.tag = 1003;
	
	[self setViews];
	[self makeLists];
	[self connectNodeViews];
	[wholeView setBackgroundColor:[UIColor blueColor]];
	[self.view addSubview:wholeView];
	
	for(NodeView *view in halfList){
		[view setBackgroundColor:[UIColor blueColor]];
		[self.view addSubview:view];
	}
	
	for(NodeView *view in quarterList){
		[view setBackgroundColor:[UIColor blueColor]];
		[self.view addSubview:view];
	}
	
	for(NodeView *view in eighthList){
		[view setBackgroundColor:[UIColor blueColor]];
		[self.view addSubview:view];
	}
	
	staff.barViews.delegate = self;
	
	[self.view addSubview:staff.barViews];
	
	currentBarView = [self getCurrentBarView];
	[staff.barViews addSubview: currentBarView];
	[self.view bringSubviewToFront: staff.barViews];
	[self.view bringSubviewToFront:infoButton];
	
	[self clearViews];
	[[staff.barList objectAtIndex:staff.currentBar] drawBar];
	[super viewDidLoad];
}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

// UIScrollView delegate method
- (void)scrollViewDidScroll:(UIScrollView *)sender {
	[staff clearStaff];
    // Switch the indicator when more than 50% of the previous/next page is visible
    CGFloat pageWidth = staff.barViews.frame.size.width;
    int barNumber = floor((staff.barViews.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
	NSLog(@"current bar is %i", barNumber);
	
    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [staff loadBarViewsWithBar:barNumber];
	
	staff.currentBar = barNumber;
	barLabel.text = [NSString stringWithFormat:@"%i", barNumber + 1];
    // A possible optimization would be to unload the views+controllers which are no longer visible
}

// UIScrollView delegate method
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
	currentBarView = [self getCurrentBarView];
	[self connectNodeViews];
	[[staff.barList objectAtIndex:staff.currentBar] drawBar];
}

- (void)playSample:(UIView *)pitch {
	isPlayingSample = pitch;
	NSString *sampleNoteNumber;
	NSString *samplePath;
	sampleNoteNumber = [NSString stringWithFormat:@"%i", [[pitchList objectAtIndex:[staffList indexOfObject: pitch]]intValue]];
	
	// initialize the audioPlayer
	samplePath = [[NSBundle mainBundle] pathForResource:sampleNoteNumber ofType:@"mp3"];
	samplePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:samplePath] error:nil];
	
	samplePlayer.currentTime = samplePlayer.duration - 0.2;
	samplePlayer.delegate = self;
	[samplePlayer play];
}

// Delegate method to start playing the next AVAudioPlayer in the array
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
	NSLog(@"finished playing note, starting new note");
    [player release];
}

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}

-(id)initWithCoder:(NSCoder*)coder {
	staff = [[coder decodeObjectForKey:@"staff"] retain];
	for(Bar* b in staff.barList) {
		if ((NSNull *)b != [NSNull null]) {
			for(NoteNode *n in b.currentNotes) {
				NodeButton *button = [[NodeButton buttonWithType:UIButtonTypeCustom] retain];
				[button addTarget:self action:@selector(noteDraggedOut:withEvent:) forControlEvents: UIControlEventTouchDragOutside | UIControlEventTouchDragInside];
				[button addTarget:self action:@selector(notePickedUp:withEvent:) forControlEvents: UIControlEventTouchDown];
				[button addTarget:self action:@selector(noteDropped:withEvent:) forControlEvents: UIControlEventTouchUpOutside |  UIControlEventTouchUpInside];
				button.tag = n.tag;
				int shift = -39;
				BOOL noteTail; // TRUE = UP, FALSE = DOWN.
				if (button.center.y >= 118.5) {
					noteTail = FALSE;
					shift = 39;
				}
				else {
					noteTail =TRUE;
				}
				int position = button.tag % 1000;				
				UIImage *image = [self getTailImage: position andTail: noteTail];
				int width = 29;
				int height = 102;
				
				if(position == 0) {
					width = 40;
					height = 26;
					shift = 0;
				}
				else if(position == 3 && noteTail) {
					width = 54;
				}
				button.frame = CGRectMake(0, 0, width, height);
				[button setBackgroundImage: image forState:UIControlStateNormal];
				button.center = n.pos;
				[n.button release];
				n.button = button;
				button.owner = n;
				CGRect frame = staff.barViews.frame;
				frame.origin.x = frame.size.width * staff.currentBar;
				frame.origin.y = 0;
				b.barView.frame = frame;
				[b.barView addSubview: button];
			}
			[staff.barViews addSubview: b.barView];
			
		}
	}
	return self;
}

-(void)encodeWithCoder:(NSCoder*)encoder {
	[encoder encodeObject: staff forKey:@"staff"];
}

- (void)dealloc {
	for(NSNumber *num in pitchList) {
		[num release];
	}
	//[eighthList release];
	//[quarterList release];
	//[halfList release];
    [super dealloc];
}

@end
